#include <strmif.h>
#include "mkvstreamaudio.hpp"
#include "mkvcontext.hpp"
#include <cassert>
#include <algorithm>


namespace MkvMux
{


MkvStreamAudio::MkvStreamAudio(
    MkvContext& c,
    const BYTE* pb,
    ULONG cb) :
    MkvStream(c)
{
    assert(pb);
    assert(cb >= 16);

    memcpy(&m_wfx, pb, std::min(size_t(cb), sizeof(WAVEFORMATEXTENSIBLE)));
    
    const WAVEFORMATEX& wfx = m_wfx.Format;
    assert((cb < 18) || (wfx.cbSize >= 0));
    assert(wfx.nChannels >= 1);
    assert(wfx.nSamplesPerSec > 0);  //TODO: more checking here
    wfx;
}


const WAVEFORMATEX& MkvStreamAudio::GetFormat() const
{
    return m_wfx.Format;
}


void MkvStreamAudio::WriteTrackType()
{
    EbmlIO::File& f = m_context.m_file;
    
    f.WriteID1(0x83);     //TrackType ID
    f.Write1UInt(1);
    f.Serialize1UInt(2);  //2=audio
}


void MkvStreamAudio::WriteTrackSettings()
{
    EbmlIO::File& f = m_context.m_file;

    f.WriteID1(0xE1);  //Audio settings
    
    //allocate 2 bytes of storage for size of settings
    const __int64 begin_pos = f.SetPosition(2, STREAM_SEEK_CUR);
    
    const WAVEFORMATEX& wfx = GetFormat();
    
    f.WriteID1(0xB5);  //SamplingFrequency ID
    f.Write1UInt(4);    
    f.Serialize4Float(static_cast<float>(wfx.nSamplesPerSec));
    
    f.WriteID1(0x9F);  //Channels ID
    f.Write1UInt(2);
    f.Serialize2UInt(wfx.nChannels);
    
    const __int64 end_pos = f.GetPosition();
    
    const __int64 size_ = end_pos - begin_pos;
    assert(size_ <= USHRT_MAX);
    
    const USHORT size = static_cast<USHORT>(size_);

    f.SetPosition(begin_pos - 2);
    f.Write2UInt(size);
    
    f.SetPosition(end_pos);
}


}  //end namespace MkvMux
